package org.eenie.qeasy;

import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class TimeTrack extends View {

    //游标的笔
    private Paint mCurPaint;
    //刻度的笔
    private Paint mScalePaint;
    //脉冲的笔
    private Paint mPulsePaint;

    private Context mContext;

    private int max = 100;
    private float progress = 0;

    private int width;
    private int height;

    private int mScaleHeight = 10;
    private int mScaleDiff = 10;

    private long totalTime = 60 * 1000;

    private int mScaleColor;

    OnTriggerListener mTriggerListener;

    ObjectAnimator mCurAnim;


    private List<PulseConfig> mPulseConfigs = new ArrayList<>();
    private HashMap<Integer, PulseEntity> mPulseModeMap = new HashMap<>();
    private HashMap<Integer, PulseEntity> mHasNotice = new HashMap<>();

    public TimeTrack(Context context) {
        this(context, null);
    }

    public TimeTrack(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TimeTrack(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);

    }


    private void init(Context context, AttributeSet attrs) {
        mContext = context;

        if (attrs != null) {
            TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.TimeTrack);
            totalTime = a.getInteger(R.styleable.TimeTrack_cus_total_time, 60) * 1000;
            mScaleColor = a.getColor(R.styleable.TimeTrack_cus_scale_color, Color.BLACK);
            a.recycle();
        }


        mCurPaint = new Paint();
        mCurPaint.setStrokeWidth(dp2px(1));
        mCurPaint.setColor(Color.GREEN);
        mCurPaint.setAntiAlias(true);


        mScalePaint = new Paint();
        mScalePaint.setStrokeWidth(dp2px(1));
        mScalePaint.setColor(mScaleColor);
        mScalePaint.setAntiAlias(true);

        mPulsePaint = new Paint();
        mPulsePaint.setStrokeWidth(dp2px(1));
        mPulsePaint.setColor(Color.parseColor("#503549FF"));
        mPulsePaint.setAntiAlias(true);
        mPulsePaint.setStyle(Paint.Style.FILL);




    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawScale(canvas);

        drawPulse(canvas);

        drawCursor(canvas);

        if (mPulseModeMap.containsKey((int) progress) && !mHasNotice.containsKey((int) progress)) {
            PulseEntity entity = mPulseModeMap.get((int) progress);
            mHasNotice.put((int) progress, entity);

            if (mTriggerListener != null) {
                mTriggerListener.onTrigger(entity);
            }
        }


        if (mTriggerListener != null) {
            mTriggerListener.onTimeChange(progress / width * totalTime/1000);
        }

    }

    private void drawPulse(Canvas canvas) {
        float unitPx = (float) width / (float) (totalTime / 1000);
        for (PulseConfig config : mPulseConfigs) {
            float startPx = config.startTime * unitPx;
            float endPx = config.startTime * unitPx + config.duration * unitPx;
            mPulsePaint.setColor(config.color);
            mPulseModeMap.put((int) startPx, new PulseEntity(config, PulseMode.START));
            mPulseModeMap.put((int) endPx, new PulseEntity(config, PulseMode.END));
            canvas.drawRect(startPx, 0, endPx, height, mPulsePaint);
        }
    }


    private void drawCursor(Canvas canvas) {
        canvas.drawLine(progress, 0, progress, height, mCurPaint);

    }

    private void drawScale(Canvas canvas) {
        float gap = (float) width / (float) max;
        for (float i = 0; i < max; i++) {
            if (i % 5 == 0) {
                canvas.drawLine(i * gap, height - dp2px(mScaleHeight) - dp2px(mScaleDiff), i * gap, height, mScalePaint);
            } else {
                canvas.drawLine(i * gap, height - dp2px(mScaleHeight), i * gap, height, mScalePaint);
            }
        }
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        width = MeasureSpec.getSize(widthMeasureSpec);
        height = MeasureSpec.getSize(heightMeasureSpec);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    private void setProgress(float progress) {
        this.progress = progress;
        postInvalidate();
    }


    public void start() {

        if (mCurAnim == null) {
            PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("progress", 0, width);
            mCurAnim = ObjectAnimator.ofPropertyValuesHolder(this, alpha);
            mCurAnim.setInterpolator(new LinearInterpolator());
        }

        mCurAnim.setDuration(totalTime);
        mCurAnim.start();
    }


    public void stop() {
        mCurAnim.cancel();
    }


    public int dp2px(final float dpValue) {
        final float scale = mContext.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    public List<PulseConfig> getPulseConfigs() {
        return mPulseConfigs;
    }

//    public void setPulseConfigs(ArrayList<PulseConfig> pulseConfigs) {
//        mPulseConfigs.clear();
//        if (pulseConfigs != null) {
//            mPulseConfigs.addAll(pulseConfigs);
//        }
//        reset();
//    }

    public void setPulseConfigs(List<PulseConfig> pulseConfigs) {
        mPulseConfigs.clear();
        if (pulseConfigs != null) {
            mPulseConfigs.addAll(pulseConfigs);
        }
        reset();
    }

    public void setTotalTime(int totalTime) {
        this.totalTime = totalTime * 1000;
        postInvalidate();
    }

    public void setScaleColor(int scaleColor) {
        mScaleColor = scaleColor;
        postInvalidate();
    }

    public void setTriggerListener(OnTriggerListener triggerListener) {
        mTriggerListener = triggerListener;
    }

    private void reset() {
        progress = 0f;
        mPulseModeMap.clear();
        mHasNotice.clear();
        if (mCurAnim != null) {
            mCurAnim.end();
        }

        postInvalidate();
    }



    public boolean isStart() {
        return mCurAnim == null ? false : mCurAnim.isStarted();
    }

    public interface OnTriggerListener {
        void onTrigger(PulseEntity entity);
        void onTimeChange(float time);
    }
}
